package com.alibaba.citrus.cr.unified.inventory.facade.service;

import com.alibaba.citrus.cr.unified.inventory.repository.AllocateRelationReadRepository;
import com.alibaba.citrus.cr.unified.inventory.repository.AllocateRelationWriteRepository;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.unified.inventory.functions.allocateRelation.AllocateRelationEntity;
import com.alibaba.citrus.cr.unified.inventory.functions.allocateRelation.AllocateRelationFactory;
import com.epoch.app.bcorder.model.dto.*;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.crplatformenhance.model.dto.BatchQueryCustomers2Request;
import com.epoch.app.crplatformenhance.model.dto.BatchQueryCustomers2Response;
import com.epoch.app.crplatformenhance.model.dto.GetLoginEmployOrganizationPermissionsRequest;
import com.epoch.app.crplatformenhance.model.dto.GetOrganiztionByIdRequest;
import com.epoch.app.crplatformenhance.model.dto.QueryCustomerInfoRequest;
import com.epoch.app.crplatformenhance.model.dto.QueryCustomerInfoResponse;

import com.epoch.app.crplatformenhance.sdo.CustomerSDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.crunifiedinventory.api.allocaterelationwrite.dto.CreateAllocateRelationByImportRequest;
import com.epoch.app.crunifiedinventory.api.allocaterelationwrite.service.AllocateRelationWriteService;
import com.epoch.app.crunifiedinventory.dto.request.CreateAllocateRelationRequest;
import com.epoch.app.crunifiedinventory.dto.request.DeleteAllocateRelationRequest;
import com.epoch.app.crunifiedinventory.dto.response.CreateAllocateRelationResponse;
import com.epoch.app.crunifiedinventory.dto.response.DeleteAllocateRelationResponse;
import com.epoch.app.crunifiedinventory.sdo.AllocateRelationSDO;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author wangcheng
 * @date 2021/10/12
 */
@Service
public class AllocateRelationWriteServiceImpl implements AllocateRelationWriteService {

    @Resource
    private AllocateRelationWriteRepository allocateRelationWriteRepository;
    @Resource
    private AllocateRelationReadRepository allocateRelationReadRepository;
    @Resource
    private CrPlatformEnhanceService otsPlatformEnhanceService;
    @Resource
    private UnifiedInventoryService unifiedInventoryService;
    @Resource
    private BaseDataService baseDataService;
    @Override
    @FacadeInvoker(value = "创建供货关系",errorCode = "OTS-04-001-00-15-012")
    public Result<CreateAllocateRelationResponse> createAllocateRelation(
        CreateAllocateRelationRequest allocateOrderCreateRequest) {
        if (Objects.isNull(allocateOrderCreateRequest.getAllocateRelationSDO())){
            return Result.fail("","创建数据不能为空");
        }
        if(StringUtils.isEmpty(allocateOrderCreateRequest.getAllocateRelationSDO().getId())) {
            AllocateRelationSDO build = AllocateRelationSDO.builder()
                    .saleChannelCode(allocateOrderCreateRequest.getAllocateRelationSDO().getSaleChannelCode())
                    .addressCode(allocateOrderCreateRequest.getAllocateRelationSDO().getAddressCode())
                    .customerCode(allocateOrderCreateRequest.getAllocateRelationSDO().getCustomerCode())
                    .departmentCode(allocateOrderCreateRequest.getAllocateRelationSDO().getDepartmentCode()).build();
            Result<Boolean> booleanResult = allocateRelationReadRepository.checkExist(build);
            if (booleanResult.getResult().booleanValue()) {

                throw new FunctionException("OTS-04-001-00-15-011");
            }

        }
        //增加组织编码的外部编码并落库
        AllocateRelationSDO allocateRelationSDO = allocateOrderCreateRequest.getAllocateRelationSDO();
        allocateRelationSDO.setDepartmentOutCode(getOrganizationOutCode(allocateRelationSDO.getDepartmentCode()));
        allocateRelationSDO.setOrganizationOutCode(getOrganizationOutCode(allocateRelationSDO.getOrganizationCode()));
        allocateRelationSDO.setSaleChannelOutCode(getOrganizationOutCode(allocateRelationSDO.getSaleChannelCode()));

        // 构造返回值 返回结果封装
        CreateAllocateRelationResponse createAllocateRelationResponse = new CreateAllocateRelationResponse();
        ArrayList<String> orderIdList = new ArrayList<>();
        //  工程构造entity
        AllocateRelationEntity allocateRelationEntity = AllocateRelationFactory.createAllocateRelation(allocateOrderCreateRequest);
        // 保存预报订单
        String id = allocateRelationEntity.create();
        orderIdList.add(id);
        return Result.success(createAllocateRelationResponse);
    }

    private String getOrganizationOutCode(String organizationId) {
        if (StringUtils.isBlank(organizationId)){
            return "";
        }
        BaselineGetOrganizationById2Request baselineGetOrganizationById2Request = new BaselineGetOrganizationById2Request();
        baselineGetOrganizationById2Request.setId(organizationId);
        Result<OrganizationSDO> organizationSDOResult = baseDataService.baselineGetOrganizationById2(baselineGetOrganizationById2Request);
        if (Objects.nonNull(organizationSDOResult)&& Objects.nonNull(organizationSDOResult.getResult())){
            return organizationSDOResult.getResult().getOutCode();
        }
        return "";
    }

    @Override
    @FacadeInvoker
    public Result<DeleteAllocateRelationResponse> deleteAllocateRelation(
        DeleteAllocateRelationRequest deleteAllocateRelationRequest) {
        DeleteAllocateRelationResponse deleteAllocateRelationResponse = new DeleteAllocateRelationResponse();
        List<String> ids = deleteAllocateRelationRequest.getIds();
        Integer count = allocateRelationWriteRepository.deleteByIds(ids);
        deleteAllocateRelationResponse.setCount(count);
        return Result.success(deleteAllocateRelationResponse);
    }

    @Override
    @FacadeInvoker
    public Result<CreateAllocateRelationResponse> modifyAllocateRelation(CreateAllocateRelationRequest modifyRequest)  {
            // 构造返回值 返回结果封装
            CreateAllocateRelationResponse createAllocateRelationResponse = new CreateAllocateRelationResponse();
            ArrayList<String> orderIdList = new ArrayList<>();
            //  工程构造entity
            AllocateRelationEntity allocateRelationEntity = AllocateRelationFactory.createAllocateRelation(modifyRequest);
            // 保存预报订单
            String id = allocateRelationEntity.create();
            orderIdList.add(id);
            return Result.success(createAllocateRelationResponse);
    }
    @Override
    @FacadeInvoker(value = "导入供货关系",errorCode = "OTS-04-001-00-15-035")
    public Result<List<AllocateRelationSDO>> createAllocateRelationByImport(
            CreateAllocateRelationByImportRequest createAllocateRelationByImportRequest) {
        Set<String> organizationCodeSet = Sets.newHashSet();
        Set<String> customerCodeSet = Sets.newHashSet();
        List<AllocateRelationSDO> allocateRelationSDOS = createAllocateRelationByImportRequest.getList();
        if (CollectionUtils.isEmpty(allocateRelationSDOS)){
            return Result.fail("","创建数据不能为空");
        }
        //为空校验
        for (AllocateRelationSDO allocateRelationSDO : allocateRelationSDOS) {
            if (StringUtils.isBlank(allocateRelationSDO.getOrganizationOutCode())){
                allocateRelationSDO.setErrorMessage("组织编码不能为空");
                continue;
            }else {
                organizationCodeSet.add(allocateRelationSDO.getOrganizationOutCode());
            }
            boolean validFlag = false;
            if (!StringUtils.isEmpty(allocateRelationSDO.getCustomerCode())){
                validFlag=true;
                customerCodeSet.add(allocateRelationSDO.getCustomerCode());
            }
            if (StringUtils.isNotEmpty(allocateRelationSDO.getSaleChannelOutCode())&&StringUtils.isNotEmpty(allocateRelationSDO.getDepartmentOutCode())){
                validFlag=true;
            }
            if (!validFlag){
                allocateRelationSDO.setErrorMessage("客户编码与渠道部门编码不能同时为空");
                continue;
            }
            if (StringUtils.isEmpty(allocateRelationSDO.getWareHouseOutCode())){
                allocateRelationSDO.setErrorMessage("销售仓库编码不能为空");
                continue;
            }
            if (StringUtils.isEmpty(allocateRelationSDO.getReceiveWareHouseOutCode())){
                allocateRelationSDO.setErrorMessage("退货仓库编码不能为空");
                continue;
            }
        }
        //查询当前登陆人的有权限的组织
        Map<String, List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> stringListMap = batchQeuryOrgMap(organizationCodeSet);
        Map<String, List<CustomerSDO>> customerInfo = getCustomerInfo(customerCodeSet);
        //批量获取外部编码对应的组织数据
        Map<String, OrganizationSDO> stringOrganizationSDOMap = GetOrganizationByOutCodes(allocateRelationSDOS);
        for (AllocateRelationSDO record : allocateRelationSDOS) {
            //组织编码    组织类型是销售组织
            if (StringUtils.isNotEmpty(record.getOrganizationOutCode())){
                //组织不为空，且组织类型为销售组织
                OrganizationSDO organizationSDO = stringOrganizationSDOMap.get(record.getOrganizationOutCode());
                if (Objects.isNull(organizationSDO)&&Objects.equals(OrganizationTypeEnum.SALES_ORGANIZATION.getCode(),organizationSDO.getType())){
                    record.setErrorMessage("组织编码异常");
                    continue;
                }
                if (Objects.isNull(stringListMap.get(record.getOrganizationOutCode()))){
                    record.setErrorMessage("组织权限不足异常");
                    continue;
                }
                record.setOrganizationName(organizationSDO.getName());
                record.setOrganizationCode(organizationSDO.getCode());
            }
            //客户编码
            if (StringUtils.isNotEmpty(record.getCustomerCode())){
                if (MapUtils.isEmpty(customerInfo) || !customerInfo.containsKey(StringUtils.trim(record.getCustomerCode()))){
                    record.setErrorMessage("客户编码异常");
                    continue;
                }
                List<CustomerSDO> customerSDOS = customerInfo.get(StringUtils.trim(record.getCustomerCode()));
                if (!CollectionUtils.isEmpty(customerSDOS)){
                    record.setCustomerName(customerSDOS.get(0).getName());
                }
            }
            //销售渠道编码   组织类型是销售渠道  parentId是销售组织id
            if (StringUtils.isNotEmpty(record.getSaleChannelOutCode())){
                //校验编码是否存在，类型是不是销售渠道 ，
                OrganizationSDO organizationSDO = stringOrganizationSDOMap.get(record.getOrganizationOutCode());
                OrganizationSDO channelSDO = stringOrganizationSDOMap.get(record.getSaleChannelOutCode());
                if (Objects.isNull(channelSDO)
                        ||!Objects.equals(OrganizationTypeEnum.SALES_CHANNEL.getCode(),channelSDO.getType())
                        ||!Objects.equals(organizationSDO.getId(),channelSDO.getParentId())){
                    record.setErrorMessage("销售渠道编码异常");
                    continue;
                }
                record.setSaleChannelName(channelSDO.getName());
                record.setSaleChannelCode(channelSDO.getCode());
            }//销售部门编码   组织类型是销售部门  parentId是销售渠道id
            if (StringUtils.isNotEmpty(record.getDepartmentOutCode())&&StringUtils.isNotEmpty(record.getSaleChannelOutCode())){
                OrganizationSDO channelSDO = stringOrganizationSDOMap.get(record.getSaleChannelOutCode());
                OrganizationSDO organizationSDO = stringOrganizationSDOMap.get(record.getDepartmentOutCode());
                if (Objects.isNull(organizationSDO)
                        ||!Objects.equals(OrganizationTypeEnum.SALES_DEPARTMENT.getCode(),organizationSDO.getType())
                        ||!Objects.equals(channelSDO.getId(),organizationSDO.getParentId())){
                    record.setErrorMessage("销售部门编码异常");
                    continue;
                }
                record.setDepartmentName(organizationSDO.getName());
                record.setDepartmentCode(organizationSDO.getCode());
            }
            //查询仓库组织下的仓库
            SearchCargoZoneListForPageRequest searchRequest=new SearchCargoZoneListForPageRequest();
            searchRequest.setSaleOrgId(stringOrganizationSDOMap.get(record.getOrganizationOutCode()).getId());
            searchRequest.setModel(3);
            searchRequest.setStatus(1);
            Integer[] types= {1,2,3,4,5};
            List<Integer> arrayList= Arrays.asList(types);
            searchRequest.setTypeList(arrayList);
            searchRequest.setLimit(200);
            SearchCargoZoneListForPageResponse warehouseList = unifiedInventoryService.searchCargoZoneListForPage(searchRequest);
            List<WarehouseInfo> result = warehouseList.getResult();
            List<String> collect = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(result)){
                 collect = result.stream().map(WarehouseInfo::getCode).collect(Collectors.toList());
            }
            //发货仓库编码
            if (StringUtils.isNotEmpty(record.getWareHouseOutCode())){
                /*QueryWarehouseByIdRequest build = QueryWarehouseByIdRequest.builder().id(record.getWareHouseOutCode()).build();
                Result<WarehouseInfo> warehouseInfoResult = unifiedInventoryService.queryWarehouseById(build);*/
                if (CollectionUtils.isEmpty(collect)||!collect.contains(StringUtils.trim(record.getWareHouseOutCode()))){
                    record.setErrorMessage("发货仓库编码异常");
                    continue;
                }
                for (WarehouseInfo warehouseInfo : result) {
                    if (Objects.equals(warehouseInfo.getCode(),StringUtils.trim(record.getWareHouseOutCode()))){
                        record.setWareHouseCode(warehouseInfo.getCode());
                        record.setWareHouseName(warehouseInfo.getName());
                    }
                }
            }//退货仓库编码
            if (StringUtils.isNotEmpty(record.getReceiveWareHouseOutCode())){
                /*QueryWarehouseByIdRequest build = QueryWarehouseByIdRequest.builder().id(record.getReceiveWareHouseOutCode()).build();
                Result<WarehouseInfo> warehouseInfoResult = unifiedInventoryService.queryWarehouseById(build);*/
                if (CollectionUtils.isEmpty(collect)||!collect.contains(StringUtils.trim(record.getReceiveWareHouseOutCode()))){
                    record.setErrorMessage("退货仓库编码异常");
                    continue;
                }
                for (WarehouseInfo warehouseInfo : result) {
                    if (Objects.equals(warehouseInfo.getCode(),StringUtils.trim(record.getReceiveWareHouseOutCode()))){
                        record.setReceiveWareHouseCode(warehouseInfo.getCode());
                        record.setReceiveWareHouseName(warehouseInfo.getName());
                    }
                }
            }
        }

        for (AllocateRelationSDO allocateRelationSDO : allocateRelationSDOS) {
            if (StringUtils.isBlank(allocateRelationSDO.getErrorMessage())){
                AllocateRelationSDO build = AllocateRelationSDO.builder()
                        .organizationCode(allocateRelationSDO.getOrganizationCode())
                        .organizationOutCode(allocateRelationSDO.getOrganizationOutCode())
                        .organizationName(allocateRelationSDO.getOrganizationName())
                        .saleChannelName(allocateRelationSDO.getSaleChannelName())
                        .saleChannelCode(allocateRelationSDO.getSaleChannelCode())
                        .saleChannelOutCode(allocateRelationSDO.getSaleChannelOutCode())
                        .customerCode(allocateRelationSDO.getCustomerCode())
                        .customerName(allocateRelationSDO.getCustomerName())
                        .departmentCode(allocateRelationSDO.getDepartmentCode())
                        .departmentName(allocateRelationSDO.getDepartmentName())
                        .departmentOutCode(allocateRelationSDO.getDepartmentOutCode())
                        .wareHouseCode(allocateRelationSDO.getWareHouseCode())
                        .wareHouseName(allocateRelationSDO.getWareHouseName())
                        .wareHouseOutCode(allocateRelationSDO.getWareHouseOutCode())
                        .receiveWareHouseCode(allocateRelationSDO.getReceiveWareHouseCode())
                        .receiveWareHouseName(allocateRelationSDO.getReceiveWareHouseName())
                        .receiveWareHouseOutCode(allocateRelationSDO.getReceiveWareHouseOutCode())
                        .isCheckInventory(allocateRelationSDO.getIsCheckInventory())
                        .isEnable(allocateRelationSDO.getIsEnable())
                        .isStrategyFirst(allocateRelationSDO.getIsStrategyFirst())
                        .build();
                //同一渠道部门组织是否存在供货关系
                Result<Boolean> booleanResult = allocateRelationReadRepository.checkExist(build);
                if (!booleanResult.getResult()){
                    String save = allocateRelationWriteRepository.save(build);
                }else {
                    allocateRelationSDO.setErrorMessage("供货关系已经存在");
                }
            }
        }
        return Result.success(allocateRelationSDOS);
    }
    private Map<String, OrganizationSDO> GetOrganizationByOutCodes(List<AllocateRelationSDO> allocateRelationSDOS){
        //根据外部编码查询组织部门渠道
        List<String> outCodes=Lists.newArrayList();
        outCodes.addAll(allocateRelationSDOS.stream().map(AllocateRelationSDO::getOrganizationOutCode).collect(Collectors.toList()));
        outCodes.addAll(allocateRelationSDOS.stream().map(AllocateRelationSDO::getSaleChannelOutCode).collect(Collectors.toList()));
        outCodes.addAll(allocateRelationSDOS.stream().map(AllocateRelationSDO::getDepartmentOutCode).collect(Collectors.toList()));
        BaselineGetOrganizationByOutCodes2Request orgRequest = BaselineGetOrganizationByOutCodes2Request.builder().outCodes(outCodes).build();
        BaselineGetOrganizationByOutCodes2Response orgResult = baseDataService.baselineGetOrganizationByOutCodes2(orgRequest);
        if (orgResult.getSuccess() && !CollectionUtils.isEmpty(orgResult.getResult())){
            Map<String,OrganizationSDO> stringOrganizationSDOMap=new HashMap<>();
            orgResult.getResult().forEach(it->stringOrganizationSDOMap.put(it.getOutCode(),it));
            return stringOrganizationSDOMap;
        }
        return new HashMap<>();
    }
    private Map<String, List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> batchQeuryOrgMap(Set<String> organizationCodeSet) {
        List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO> loginOrganizationCode = getLoginOrganizationCode(OrganizationTypeEnum.SALES_ORGANIZATION.getCode());
        Map<String, List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> organizationMap =
                loginOrganizationCode.stream()
                        .filter(organizationSDO -> organizationCodeSet.contains(organizationSDO.getCode()))
                        .collect(Collectors.groupingBy(com.epoch.app.crplatformenhance.sdo.OrganizationSDO::getOutCode));
        return organizationMap;
    }

    /**
     * 获取 登录人 所属销售组织code
     * @param type
     * @return
     */
    private List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO> getLoginOrganizationCode(Integer type) {
        GetLoginEmployOrganizationPermissionsRequest request = GetLoginEmployOrganizationPermissionsRequest.builder().type(type).build();
        Result<List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> loginEmployOrganizationPermissions = otsPlatformEnhanceService.getLoginEmployOrganizationPermissions(request);
        if (ObjectUtils.isEmpty(loginEmployOrganizationPermissions)) {
            return new ArrayList<>();
        }
        List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO> result = loginEmployOrganizationPermissions.getResult();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(result)) {
            return new ArrayList<>();
        }
        return result;
    }

    /**
     * 批量查询客户信息
     * @param
     * @return
     */
    private Map<String, List<CustomerSDO>> getCustomerInfo(Set<String> customerCodeSet) {
        List<String> customerCodes = new ArrayList<>(customerCodeSet);
        BatchQueryCustomers2Request build = BatchQueryCustomers2Request.builder().codes(customerCodes).build();
        BatchQueryCustomers2Response batchQueryCustomers2Response = otsPlatformEnhanceService.batchQueryCustomers2(build);
        if (batchQueryCustomers2Response.getSuccess() && !CollectionUtils.isEmpty(batchQueryCustomers2Response.getResult()) ){
            return batchQueryCustomers2Response.getResult().stream().collect(Collectors.groupingBy(CustomerSDO::getCode));
        }
        return new HashMap<>();
    }
}
